﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.ServiceLocation;
using Pap.Core.Utilities;
using Pap.Data;
using Pap.Data.Abstraction.Utils;
using Pap.Services;
using Pap.Services.WorkflowEngine;
using Pap.Web.Utils;

namespace Pap.Web.Modules.Loan.ViewModel
{
    /// <summary>
    /// 
    /// </summary>
    public class LoanReschedulingViewModel : IViewModel
    {
        /// <summary>
        /// 
        /// </summary>
        ILoanRepository _LoanRepository;
        /// <summary>
        /// 
        /// </summary>
        ILoanExecutionService _LoanExecutionService;
        /// <summary>
        /// 
        /// </summary>
        IWorkflowService _WfService;
        /// <summary>
        /// Initializes a new instance of the <see cref="LoanReschedulingViewModel"/> class.
        /// </summary>
        /// <param name="loanRepository">The loan repository.</param>
        /// <param name="loanExecutionService">The loan execution service.</param>
        /// <param name="workflowService">The workflow service.</param>
        public LoanReschedulingViewModel(ILoanRepository loanRepository, ILoanExecutionService loanExecutionService, IWorkflowService workflowService)
        {
            _LoanRepository = loanRepository;
            _LoanExecutionService = loanExecutionService;
            _WfService = workflowService;
        }


        /// <summary>
        /// Gets the loan.
        /// </summary>
        /// <param name="LoanID">The loan ID.</param>
        /// <returns></returns>
        public ICustomerLoan GetLoan(Guid LoanID)
        {
            return _LoanRepository.GetCustomerLoanByID(LoanID);
        }


        /// <summary>
        /// Gets the loan dues.
        /// </summary>
        /// <param name="loanID">The loan ID.</param>
        /// <returns></returns>
        public double getLoanDues(Guid loanID)
        {
            var execution = _LoanRepository.GetCustomerLoanByID(loanID).LoanExecutionLst.Where(loanEx => loanEx.LoanExecutionStatus).OrderBy(loanEx => loanEx.ExecutionDate).First();
            double dues = execution.LoanExecutionInstallmentsLst.Select(Inst => Inst.TotalInstallmentAmount).Sum() -
                execution.LoanExecutionInstallmentsLst.SelectMany(inst => inst.LoanInstallmentPaymentLst).Select(paymen => paymen.PaymentAmount).Sum();

            return dues;
        }

        /// <summary>
        /// Reschedules the specified loan ID.
        /// </summary>
        /// <param name="loanID">The loan ID.</param>
        /// <param name="executionDate">The execution date.</param>
        /// <param name="paymentPeriod">The payment period.</param>
        /// <param name="attachmentsID">The attachments ID.</param>
        /// <param name="deletedIDs">The deleted I ds.</param>
        public void Reschedule(Guid loanID, DateTime executionDate, int paymentPeriod, IEnumerable<Guid> attachmentsID, IEnumerable<Guid> deletedIDs)
        {
            using (IUnitOfWork trancaction = ServiceLocator.Current.GetInstance<IUnitOfWork>())
            {
                double loanAmount = getLoanDues(loanID);
                ICustomerLoan loan = _LoanRepository.GetCustomerLoanByID(loanID);
                var lastLoanExecution = loan.LoanExecutionLst.Where(loanEx => loanEx.LoanExecutionStatus).OrderBy(loanex => loanex.ExecutionDate).Last();
                ILoanExecution newLoanExecution = _LoanExecutionService.CreateLoanExecution(lastLoanExecution, executionDate, paymentPeriod, loanAmount);
                _LoanRepository.CreateLoanExecution(newLoanExecution);

                foreach (var item in attachmentsID)
                {
                    if (newLoanExecution.LoanExecutionAttachmentsLst.Where(att => att.Attachment == item).Count() == 0)
                    {
                        ILoanExecutionAttachment attachment = ServiceLocator.Current.GetInstance<ILoanExecutionAttachment>();
                        attachment.LoanExecutionAttachmentID = Guid.NewGuid();
                        attachment.LoanExecutionID = newLoanExecution.LoanExecutionID;
                        attachment.Attachment = item;
                        _LoanRepository.CreateLoanExecutionAttachment(attachment);
                    }
                }
                foreach (var imageID in deletedIDs)
                {
                    ILoanExecutionAttachment att = _LoanRepository.FindLoanExecutionAttachments(a => a.Attachment == imageID).FirstOrDefault();
                    if (att != null)
                    {
                        _LoanRepository.DeleteLoanExecutonAttachment(att);
                    }
                }

                var processInstID = _WfService.GetProcessInstanceIDByEntity(loanID);
                _WfService.Move(ActionTypes.Reschedule, processInstID, RegistryInfo.UserID, string.Empty, null);
                trancaction.Commit();
            }
        }

        /// <summary>
        /// Gets the execution installments.
        /// </summary>
        /// <param name="loanID">The loan ID.</param>
        /// <param name="executionDate">The execution date.</param>
        /// <param name="paymentPeriod">The payment period.</param>
        /// <returns></returns>
        public IEnumerable<ILoanExecutionInstallment> GetExecutionInstallments(Guid loanID, DateTime executionDate, int paymentPeriod)
        {
            double loanAmount = getLoanDues(loanID);
            ICustomerLoan loan = _LoanRepository.GetCustomerLoanByID(loanID);
            var lastLoanExecution = loan.LoanExecutionLst.Where(loanEx => loanEx.LoanExecutionStatus).OrderBy(loanex => loanex.ExecutionDate).Last();
            ILoanExecution newLoanExecution = _LoanExecutionService.CreateLoanExecution(lastLoanExecution, executionDate, paymentPeriod, loanAmount);
            return _LoanExecutionService.CreateLoanExecutionInstallments(newLoanExecution);
        }
    }
}
